package org.lisy.java.io;

import java.io.File;
import java.io.FileInputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.linuxense.javadbf.DBFDataType;
import com.linuxense.javadbf.DBFField;
import com.linuxense.javadbf.DBFReader;
import com.linuxense.javadbf.DBFWriter;

/**
 * DBF 文件生成
 * 
 * @author lisy
 */
public class DbfOperate {
	
	// 目标CSV文件目录
	private final static String TARGET_DBF_FILE_DIR = "./deploy/target/dbf";
	// 目标CSV文件
	private final static String TARGET_DBF_FILE = "target.dbf";
	
	public static void main(String[] args) {
		// 标题名 字段名称不能超过11个字节（或者5个中文字符）
		String[] strutName = {"id","name","salary", "time", "reamrk", "isAdult"};
		
		// 获取标题
        DBFField[] fields = getField(strutName);
        
        // 获取数据
        List<Object[]> data = getData(strutName);
		
        // 准备生成文件
		writeFile(fields, data);
		
		// 读取生成的文件
		readFile();
	}

	/**
	 * 获取文件头
	 * 
	 * @param strutName 标题
	 * @return
	 */
	private static DBFField[] getField(String[] strutName) {
		int fieldCount = strutName.length;
		/**
		 * 六种类型
		 * FIELD_TYPE_C 字符串
		 * FIELD_TYPE_N 数值 Double
		 * FIELD_TYPE_F 数值 Double
		 * FIELD_TYPE_D 日期 Date
		 * FIELD_TYPE_L 布尔 Boolean
		 * FIELD_TYPE_M 不知道是啥
		 */
		DBFDataType[] strutType = new DBFDataType[fieldCount];
		strutType[0] = DBFDataType.NUMERIC;
		strutType[1] = DBFDataType.CHARACTER;
		strutType[2] = DBFDataType.FLOATING_POINT;
		strutType[3] = DBFDataType.DATE;
		strutType[4] = DBFDataType.CHARACTER;
		strutType[5] = DBFDataType.LOGICAL;
		
		// 字段长度 字符类型的字段，数据最大不能超过255个字节
		int[] strutLength = new int[fieldCount];
		strutLength[0] = 16;
		strutLength[1] = 254;
		strutLength[2] = 16;
		strutLength[3] = 20;
		strutLength[4] = 100;
		strutLength[5] = 1;
		
		// 小数位数
		int[] strutCount = new int[fieldCount];
		strutCount[0] = 0;
		strutCount[1] = 0;
		strutCount[2] = 2;
		strutCount[3] = 0;
		strutCount[4] = 0;
		strutCount[5] = 0;
		
		// 组装文件头
        DBFField[] fields = new DBFField[fieldCount];
        for (int i = 0; i < fieldCount; i++) {
        	fields[i] = new DBFField();
            fields[i].setName(strutName[i]);
            fields[i].setType(strutType[i]);
            // 数值字段
        	if (DBFDataType.FLOATING_POINT == strutType[i] || DBFDataType.NUMERIC == strutType[i]) {
        		fields[i].setLength(strutLength[i]);
        		fields[i].setDecimalCount(strutCount[i]);
        	}
        	// 字符串字段，布尔字段
        	if (DBFDataType.CHARACTER == strutType[i] || DBFDataType.LOGICAL == strutType[i]) {
        		fields[i].setLength(strutLength[i]);
        	}
        }
		return fields;
	}
	
	/**
	 * 获取数据
	 * 
	 * @param strutName 标题
	 * @return
	 */
	private static List<Object[]> getData(String[] strutName) {
		List<Object[]> data = new ArrayList<Object[]>();
		Object[] row1 = new Object[strutName.length];
		row1[0] = null;
		row1[1] = "user1中文乱码";
		row1[2] = 2000.12;
		row1[3] = new Date();
		row1[4] = "remark";
		row1[5] = true;
		data.add(row1);
		
		Object[] row2 = new Object[strutName.length];
		row2[0] = Double.valueOf(2.5);
		row2[1] = "user2";
		row2[2] = 200.13;
		row2[3] = new Date();
		row2[4] = "remark";
		row2[5] = false;
		data.add(row2);
		
		Object[] row3 = new Object[strutName.length];
		row3[0] = Double.valueOf(3.1);
		row3[1] = "user3";
		row3[2] = 2000.12;
		row3[3] = new Date();
		row3[4] = "remark";
		row3[5] = true;
		data.add(row3);
		return data;
	}

	/**
	 * 生成文件
	 * @param fields 文件头
	 * @param data 数据
	 */
	public static void writeFile(DBFField[] fields, List<Object[]> data) {
		DBFWriter writer = null;
        try {
        	String filePath = TARGET_DBF_FILE_DIR + File.separator + TARGET_DBF_FILE;
        	File file = new File(filePath);
        	if (file.exists()) {
        		file.delete();
        	} else {
        		// 如果上级不存在，就会自动创建
				file.getParentFile().mkdirs();
        	}
        	// 设置GBK编码避免中文乱码
        	Charset charset = Charset.forName("GBK");
        	// 初始化方式防止内存溢出，若已有文件可以续写
            writer = new DBFWriter(new File(filePath), charset);
            writer.setFields(fields);
            int num = 0;
            for (int i = 0; i < data.size(); i++) {
                writer.addRecord(data.get(i));
                num++;
            }
            System.out.println("write " + num + " data!");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("write file fail!" + e.toString());
        } finally {
        	if (writer != null) {
        		writer.close();
        	}
        }
    }
	
	/**
	 * 读取文件
	 */
	private static void readFile() {
        DBFReader dbfReader = null;
        try {
        	String filePath = TARGET_DBF_FILE_DIR + File.separator + TARGET_DBF_FILE;
        	File file = new File(filePath);
        	// 设置GBK编码避免中文乱码
        	Charset charset = Charset.forName("GBK");
            dbfReader = new DBFReader(new FileInputStream(file), charset);
            Object[] rowValues;
            int num = 0;
            while ((rowValues = dbfReader.nextRecord()) != null) {
            	if (num == 0) {
            		StringBuffer sb = new StringBuffer();
            		for (int i = 0; i < rowValues.length; i++) {
                        sb.append(dbfReader.getField(i).getName()).append(",");
                    }
            		sb = sb.deleteCharAt(sb.length() - 1);
            		System.out.println(sb);
            	}
            	StringBuffer sb=new StringBuffer();
                for (int i = 0; i < rowValues.length; i++) {
                    sb.append(rowValues[i]).append(",");
                }
                sb = sb.deleteCharAt(sb.length() - 1);
                System.out.println(sb);
                num++;
            }
            System.out.println("read " + num + " data!");
        } catch (Exception e) {
        	 e.printStackTrace();
             System.out.println("read file fail!" + e.toString());
        } finally {
        	if (dbfReader != null) {
        		dbfReader.close();
        	}
        }
	}
	
}
